package fr.imag.ufrima.ima.project.ui.tools;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.text.DecimalFormat;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.apache.log4j.Logger;

import fr.imag.ufrima.ima.project.core.Filter;
import fr.imag.ufrima.ima.project.core.operations.FilterOperations;
import fr.imag.ufrima.ima.project.ui.main.ImageProject;

public class FilterTool extends JPanel implements ActionListener {
	private Logger logger = Logger.getLogger(getClass().getName());
	
	private ImageProject imageProject;
	private JComboBox cmbPredefinedFilters;
	private JTextField txtP11;
	private JTextField txtP12;
	private JTextField txtP13;
	private JTextField txtP21;
	private JTextField txtP22;
	private JTextField txtP23;
	private JTextField txtP31;
	private JTextField txtP32;
	private JTextField txtP33;
	private JCheckBox chkCustomFilter;
	
	/**
	 * Create the panel.
	 */
	public FilterTool(ImageProject imageProject) {
		this.imageProject = imageProject;
		
		setLayout(new BorderLayout(0, 0));
		
		JPanel panel = new JPanel();		
		GridBagLayout gbl_panel = new GridBagLayout();
		gbl_panel.columnWidths = new int[]{150};
		gbl_panel.rowHeights = new int[]{30, 30, 120, 30, 30};
		gbl_panel.columnWeights = new double[]{1.0};
		gbl_panel.rowWeights = new double[]{Double.MIN_VALUE, 0.0, 0.0, 1.0, 0.0};
		panel.setLayout(gbl_panel);

		add(panel, BorderLayout.NORTH);
		
		JLabel lblPredefined = new JLabel("Predéfinis:");
		GridBagConstraints gbc_lblPredefined = new GridBagConstraints();
		gbc_lblPredefined.anchor = GridBagConstraints.WEST;
		gbc_lblPredefined.insets = new Insets(5, 0, 5, 0);
		gbc_lblPredefined.gridx = 0;
		gbc_lblPredefined.gridy = 0;
		panel.add(lblPredefined, gbc_lblPredefined);
		
		cmbPredefinedFilters = new JComboBox();
		cmbPredefinedFilters.setModel(new DefaultComboBoxModel(new String[] {"Moyenne 3x3", "Gauss 3x3", "Rehausse 3x3", "Flou 3x3", "Accentuation 3x3", "Laplacien 3x3"}));
		GridBagConstraints gbc_cmbPredefiniedFilters = new GridBagConstraints();
		gbc_cmbPredefiniedFilters.insets = new Insets(5, 0, 5, 0);
		gbc_cmbPredefiniedFilters.fill = GridBagConstraints.HORIZONTAL;
		gbc_cmbPredefiniedFilters.gridx = 0;
		gbc_cmbPredefiniedFilters.gridy = 1;
		cmbPredefinedFilters.addActionListener(this);		
		panel.add(cmbPredefinedFilters, gbc_cmbPredefiniedFilters);
		
		
		JButton btnNewButton = new JButton("Appliquer");
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				FilterTool.this.doFilter();
			}
		});
		
		JPanel panel_1 = new JPanel();
		GridBagConstraints gbc_panel_1 = new GridBagConstraints();
		gbc_panel_1.insets = new Insets(10, 0, 10, 0);
		gbc_panel_1.fill = GridBagConstraints.BOTH;
		gbc_panel_1.gridx = 0;
		gbc_panel_1.gridy = 2;
		panel.add(panel_1, gbc_panel_1);
		GridBagLayout gbl_panel_1 = new GridBagLayout();
		gbl_panel_1.columnWidths = new int[]{30, 30, 30};
		gbl_panel_1.rowHeights = new int[]{30, 30, 30};
		gbl_panel_1.columnWeights = new double[]{1.0, 1.0, 1.0};
		gbl_panel_1.rowWeights = new double[]{1.0, 1.0, 1.0};
		panel_1.setLayout(gbl_panel_1);
		
		txtP11 = new JTextField();
		txtP11.setEditable(false);
		txtP11.setText("0.0");
		GridBagConstraints gbc_txtP11 = new GridBagConstraints();
		gbc_txtP11.insets = new Insets(0, 0, 5, 5);
		gbc_txtP11.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtP11.gridx = 0;
		gbc_txtP11.gridy = 0;
		panel_1.add(txtP11, gbc_txtP11);
		txtP11.setColumns(10);
		
		txtP21 = new JTextField();
		txtP21.setEditable(false);
		txtP21.setText("0.0");
		GridBagConstraints gbc_txtP21 = new GridBagConstraints();
		gbc_txtP21.insets = new Insets(0, 0, 5, 5);
		gbc_txtP21.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtP21.gridx = 1;
		gbc_txtP21.gridy = 0;
		panel_1.add(txtP21, gbc_txtP21);
		txtP21.setColumns(10);
		
		txtP31 = new JTextField();
		txtP31.setEditable(false);
		txtP31.setText("0.0");
		GridBagConstraints gbc_txtP31 = new GridBagConstraints();
		gbc_txtP31.insets = new Insets(0, 0, 5, 5);
		gbc_txtP31.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtP31.gridx = 2;
		gbc_txtP31.gridy = 0;
		panel_1.add(txtP31, gbc_txtP31);
		txtP31.setColumns(10);
		
		txtP12 = new JTextField();
		txtP12.setEditable(false);
		txtP12.setText("0.0");
		GridBagConstraints gbc_txtP12 = new GridBagConstraints();
		gbc_txtP12.insets = new Insets(0, 0, 5, 5);
		gbc_txtP12.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtP12.gridx = 0;
		gbc_txtP12.gridy = 1;
		panel_1.add(txtP12, gbc_txtP12);
		txtP12.setColumns(10);
		
		txtP22 = new JTextField();
		txtP22.setEditable(false);
		txtP22.setText("0.0");
		GridBagConstraints gbc_txtP22 = new GridBagConstraints();
		gbc_txtP22.insets = new Insets(0, 0, 5, 5);
		gbc_txtP22.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtP22.gridx = 1;
		gbc_txtP22.gridy = 1;
		panel_1.add(txtP22, gbc_txtP22);
		txtP22.setColumns(10);
		
		txtP32 = new JTextField();
		txtP32.setEditable(false);
		txtP32.setText("0.0");
		GridBagConstraints gbc_txtP32 = new GridBagConstraints();
		gbc_txtP32.insets = new Insets(0, 0, 5, 5);
		gbc_txtP32.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtP32.gridx = 2;
		gbc_txtP32.gridy = 1;
		panel_1.add(txtP32, gbc_txtP32);
		txtP32.setColumns(10);
		
		txtP13 = new JTextField();
		txtP13.setEditable(false);
		txtP13.setText("0.0");
		GridBagConstraints gbc_txtP13 = new GridBagConstraints();
		gbc_txtP13.insets = new Insets(0, 0, 5, 5);
		gbc_txtP13.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtP13.gridx = 0;
		gbc_txtP13.gridy = 2;
		panel_1.add(txtP13, gbc_txtP13);
		txtP13.setColumns(10);
		
		txtP23 = new JTextField();
		txtP23.setEditable(false);
		txtP23.setText("0.0");
		GridBagConstraints gbc_txtP23 = new GridBagConstraints();
		gbc_txtP23.insets = new Insets(0, 0, 5, 5);
		gbc_txtP23.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtP23.gridx = 1;
		gbc_txtP23.gridy = 2;
		panel_1.add(txtP23, gbc_txtP23);
		txtP23.setColumns(10);
		
		txtP33 = new JTextField();
		txtP33.setEditable(false);
		txtP33.setText("0.0");
		GridBagConstraints gbc_txtP33 = new GridBagConstraints();
		gbc_txtP33.insets = new Insets(0, 0, 5, 5);
		gbc_txtP33.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtP33.gridx = 2;
		gbc_txtP33.gridy = 2;
		panel_1.add(txtP33, gbc_txtP33);
		txtP33.setColumns(10);
		
		chkCustomFilter = new JCheckBox("Personnalisé");
		GridBagConstraints gbc_chkCustomFilter = new GridBagConstraints();
		gbc_chkCustomFilter.anchor = GridBagConstraints.WEST;
		gbc_chkCustomFilter.insets = new Insets(0, 0, 5, 0);
		gbc_chkCustomFilter.gridx = 0;
		gbc_chkCustomFilter.gridy = 3;
		chkCustomFilter.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				FilterTool.this.changeCustomState();
			}
		});
		panel.add(chkCustomFilter, gbc_chkCustomFilter);
		
		
		GridBagConstraints gbc_btnNewButton = new GridBagConstraints();
		gbc_btnNewButton.insets = new Insets(5, 0, 5, 0);
		gbc_btnNewButton.gridx = 0;
		gbc_btnNewButton.gridy = 4;
		panel.add(btnNewButton, gbc_btnNewButton);
		
		cmbPredefinedFilters.setSelectedIndex(0);
	}
	
	private void changeCustomState() {		
		this.setEditableTexts(this.chkCustomFilter.isSelected());
		if (!this.chkCustomFilter.isSelected()) {
			this.cmbPredefinedFilters.setSelectedIndex(0);
		}
	}
	
	private void doFilter() {		
		imageProject.setWaitCursor();
				
		Filter filter;		
		if (!chkCustomFilter.isSelected()) {
			filter = new Filter(Filter.getFilterByKey(cmbPredefinedFilters.getSelectedIndex()));	
		}
		else {
			filter = new Filter(this.getCustomFilter());
		}	
		
		FilterOperations filterOperations = new FilterOperations(imageProject.getCurrentImageDocument().getImage());
		filterOperations.setFilter(filter);
		
		BufferedImage resultImage = filterOperations.doOperation();
		imageProject.getCurrentImageDocument().getImage().modifyWithImage(resultImage);

		imageProject.getCurrentImageDocument().repaint();

		imageProject.setNormalCursor();
	}

	private float[] getCustomFilter() {
		float[] filter;
		
		filter = new float[9];
		filter[0] = Float.parseFloat(txtP11.getText());
		filter[1] = Float.parseFloat(txtP21.getText());
		filter[2] = Float.parseFloat(txtP31.getText());
		
		filter[3] = Float.parseFloat(txtP12.getText());
		filter[4] = Float.parseFloat(txtP22.getText());
		filter[5] = Float.parseFloat(txtP32.getText());
		
		filter[6] = Float.parseFloat(txtP13.getText());
		filter[7] = Float.parseFloat(txtP23.getText());
		filter[8] = Float.parseFloat(txtP33.getText());
		
		return filter;
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		if (e.getSource() instanceof JComboBox) {
			
			logger.debug(String.format("actionPerformed with index: %d", cmbPredefinedFilters.getSelectedIndex()));
			
			float[] filter = Filter.getFilterByKey(cmbPredefinedFilters.getSelectedIndex());
			DecimalFormat format = new DecimalFormat("#0.00");
			txtP11.setText(format.format(filter[0]));
			txtP21.setText(format.format(filter[1]));
			txtP31.setText(format.format(filter[2]));
			
			txtP12.setText(format.format(filter[3]));
			txtP22.setText(format.format(filter[4]));
			txtP32.setText(format.format(filter[5]));
			
			txtP13.setText(format.format(filter[6]));
			txtP23.setText(format.format(filter[7]));
			txtP33.setText(format.format(filter[8]));			
		}
	}

	private void setEditableTexts(boolean editable) {
		txtP11.setEditable(editable);
		txtP21.setEditable(editable);
		txtP31.setEditable(editable);
		
		txtP12.setEditable(editable);
		txtP22.setEditable(editable);
		txtP32.setEditable(editable);
		
		txtP13.setEditable(editable);
		txtP23.setEditable(editable);
		txtP33.setEditable(editable);
	}
}
